package utils.csv;

import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.exceptions.CsvValidationException;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;

import java.io.*;
import java.util.ArrayList;
import java.util.List;


/**
 * CSV工具类   格式转换、格式验证、格式化功能
 */

public class CsvUtils {

    /***
     *实现CSV转JSON
     * @param url 文件地址
     */

    public static String csv2Json(String url) {
        int hang = 0;    //行数容器
        StringBuilder jsonBuilder = new StringBuilder();    //json文件容器
        String[] strName = new String[0];    //属性名容器
        String[] strC;

        CSVReader reader = null;
        try {
            reader = new CSVReader(new FileReader(url));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }

        boolean flag = false;
        while (true) {
            try {
                StringBuilder strJ = new StringBuilder();
                strC = reader.readNext();
                if (strC == null) break;   //没有下一行，退出
                hang++;    //行数自增
                if (hang == 1) {    //第一行是属性名,属性名应该做标签
                    strName = strC.clone();    //把属性名拿出来
                    continue;
                }
                for (int k = 0; k < strName.length; k++) {
                    if (!(strName[k].startsWith("\"") && strName[k].endsWith("\""))) {
                        strName[k] = "\"" + strName[k] + "\"";    //给没引号包裹的加上引号
                    }
                }
                int i = 0;
                strJ.append("\t{\n\t\t");    //一组参数头的缩进与大括号并换行和下一行缩进
                while (i < strName.length) {
                    try {
                        // 尝试将字符串转换为浮点数
                        Double.parseDouble(strC[i]);
                    } catch (NumberFormatException e1) {    //转换失败加引号
                        flag = true;
                    }

                    if ("true".equalsIgnoreCase(strC[i])) {
                        flag = false;
                        strC[i] = "true";
                    }
                    if ("false".equalsIgnoreCase(strC[i])) {
                        flag = false;
                        strC[i] = "false";
                    }
                    if (flag) {    //不能转换
                        if (strC[i].startsWith("\"") && strC[i].endsWith("\"")) {
                            continue;
                        } else {
                            strC[i] = "\"" + strC[i] + "\"";    //给没引号包裹的加上引号
                        }
                        flag = false;
                    }
                    strJ.append(strName[i].trim()).append(" : ").append(strC[i].trim());
                    if (i == strName.length - 1) {
                        strJ.append("\n");    //一组参数里最后一个参数，不要逗号，换行
                    } else {
                        strJ.append(",\n\t\t");    //逗号分割同一组的不同参数并换行和下一行缩进
                    }
                    i++;
                }
                strJ.append("\t},\n");    //一组参数结尾的大括号和逗号并换行
                jsonBuilder.append(strJ);
            } catch (CsvValidationException | IOException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            reader.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        int length = jsonBuilder.length();
        if (length > 0) {
            jsonBuilder.setLength(length - 2);  // 去除最后一组参数后的逗号和换行符
        }
        if (hang != 0) {    //不是空文件
            jsonBuilder.insert(0, "[\n");
            jsonBuilder.append("\n]");
        }

        return jsonBuilder.toString();
    }


    /***
     *实现CSV转XML
     * @param url 文件地址
     */

    public static String csv2Xml(String url) {
        int hang = 0;    //行数容器
        StringBuilder xmlBuilder = new StringBuilder();    //XML文件容器
        String[] strName = new String[0];    //属性名容器
        String[] strC;

        CSVReader reader = null;
        try {
            reader = new CSVReader(new FileReader(url));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }

        while (true) {
            try {
                StringBuilder strJ = new StringBuilder();
                strC = reader.readNext();
                if (strC == null) break;
                hang++;    //行数自增
                if (hang == 1) {    //第一行是属性名,属性名应该做标签
                    strName = strC.clone();    //把属性名拿出来
                    continue;
                }
                int i = 0;
                strJ.append("\t<record>\n");    //缩进，一组数据的开始标签，换行
                while (i < strName.length) {
                    strJ.append("\t\t<").append(strName[i]).append(">").append(strC[i]).append("</").append(strName[i]).append(">\n");
                    i++;
                }
                strJ.append("\t</record>\n");    //缩进，一组数据的结束标签，换行
                xmlBuilder.append(strJ);
            } catch (CsvValidationException | IOException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            reader.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        if (hang != 0) {    //不是空文件
            xmlBuilder.insert(0, "<dataset>\n");
            xmlBuilder.append("</dataset>");
        }

        return xmlBuilder.toString();
    }


    /***
     *实现Csv转XML
     * @param url 文件地址
     */

    public static String csv2Yaml(String url) {
        int hang = 0;    //行数容器
        StringBuilder yamlBuilder = new StringBuilder();    //YAML文件容器
        String[] strName = new String[0];    //属性名容器
        String[] strC;

        CSVReader reader = null;
        try {
            reader = new CSVReader(new FileReader(url));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }

        while (true) {
            try {
                StringBuilder strJ = new StringBuilder();
                strC = reader.readNext();
                if (strC == null) break;
                hang++;    //行数自增
                if (hang == 1) {    //第一行是属性名,属性名应该做标签
                    strName = strC.clone();    //把属性名拿出来
                    continue;
                }
                int i = 0;
                strJ.append("-\n");    //一组数据的头
                while (i < strName.length) {
                    strJ.append(" ").append(strName[i]).append(": ").append(strC[i]).append("\n");    //缩进，键值对key: value，换行
                    i++;
                }
                yamlBuilder.append(strJ);
            } catch (CsvValidationException | IOException e) {
                throw new RuntimeException(e);
            }
        }
        try {
            reader.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return yamlBuilder.toString();
    }


    /***
     *实现CSV格式验证
     * @param url 文件地址
     * @param gt 分隔符
     * @author xsb
     */

    public static boolean csvValidator(String url, String gt) {
        try (CSVReader reader = new CSVReader(new FileReader(url))) {
            String[] headers = reader.readNext();
            if (headers == null || headers.length == 0) {
                System.out.println("CSV文件头部为空.");
                return false;
            }

            int expectedNumColumns = headers.length;

            String[] record;
            while ((record = reader.readNext()) != null) {
                if (record.length != expectedNumColumns) {

                    System.out.println("CSV文件的行 " + reader.getLinesRead() + " 列数与头部不匹配.");
                    return false;
                }
            }

            return true;
        } catch (IOException | CsvValidationException e) {
            e.printStackTrace();
            return false;
        }

    }

    /***
     *实现CSV格式规范
     * @param url 文件地址
     */

    public static String csvFormatter(String url) {
        // 设置 CSV 格式
        CSVFormat csvFormat = CSVFormat.RFC4180.withFirstRecordAsHeader();

        // 设置输入文件和输出文件
        File inputFile = new File(url);

        // 设置输入文件的流
        try (Reader reader = new BufferedReader(new FileReader(inputFile));
             StringWriter stringWriter = new StringWriter();
             CSVParser csvParser = new CSVParser(reader, csvFormat);
             CSVPrinter csvPrinter = new CSVPrinter(stringWriter, csvFormat)) {

            // 处理表头
            String[] s_head = csvParser.getHeaderMap().keySet().toString().replace("[", "").replace("]", "").split(",");
            int j = 0;
            while (j < s_head.length) {
                s_head[j] = s_head[j].trim();
                j++;
            }
            csvPrinter.printRecord(s_head);
            // 处理数据行
            List<CSVRecord> records = csvParser.getRecords();
            for (int rowNumber = 0; rowNumber < records.size(); rowNumber++) {
                CSVRecord record = records.get(rowNumber);
                if (record.size() == 0) {
                    continue; // 跳过空白行
                }
                List<String> normalizedRow = new ArrayList<>();
                // 处理每个单元格
                for (int i = 0; i < record.size(); i++) {
                    String cellValue = record.get(i);
                    if (cellValue != null && !cellValue.isEmpty()) {
                        normalizedRow.add(cellValue.trim());
                    }
                }
                if (!normalizedRow.isEmpty()) {
                    csvPrinter.printRecord(normalizedRow);
                }
            }

            // 将内容输出为字符串
            csvPrinter.flush();
            return stringWriter.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}